<template>
  <div class="container">
    <div id="modeler">
      <!-- 画布区域 -->
      <div id="canvas" ref="canvas"></div>
      <!-- 侧边栏区域 -->
      <div id="properties" class="panel"></div>
    </div>
    <div class="action">
      <!-- 关于打开文件的这个我使用了Element的文件上传组件，在上传前钩子获取到文件然后读取文件内容 -->
      <el-upload :before-upload="openFile"
                 action="string" style="margin-right: 12px">
        <el-button type="primary">
          <el-icon>
            <component :is="`el-icon-${toLine('FolderOpened')}`"></component>
          </el-icon>
          打开文件
        </el-button>
      </el-upload>
      <el-button id="download" @click="download()" type="primary">
        <el-icon>
          <component :is="`el-icon-${toLine('Download')}`"></component>
        </el-icon>
        下载BMPMN
      </el-button>
      <el-button @click="upload()" type="primary">
        <el-icon>
          <component :is="`el-icon-${toLine('Upload')}`"></component>
        </el-icon>
        上传部署
      </el-button>
    </div>
  </div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { toLine } from '../../../../utils/index'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import BpmnModeler from 'bpmn-js/lib/Modeler.js'
// 侧边栏样式
import 'bpmn-js-properties-panel/dist/assets/element-templates.css'
import 'bpmn-js-properties-panel/dist/assets/properties-panel.css'
import { BpmnPropertiesPanelModule, BpmnPropertiesProviderModule, CamundaPlatformPropertiesProviderModule } from 'bpmn-js-properties-panel/dist/index.esm.js'
import CamundaBpmnModdle from 'camunda-bpmn-moddle/resources/camunda.json'
import { translate, newDiagram } from '@/components/bpmn/src/index.js'
let bpmnModeler: any
const initModeler = () => {
  // 创建BpmnModeler 加markRaw去除双向绑定作用域
  bpmnModeler =
    // markRaw(
    new BpmnModeler({
      // 渲染容器
      container: '#canvas',
      // 使用键盘快捷键
      keyboard: {
        bindTo: window
      },
      // 加入工具栏支持
      propertiesPanel: {
        // 侧边栏挂载的 Dom Id
        parent: '#properties'
      },
      // 自定义且与默认扩展包一起使用的模块列表
      // Activiti Platform
      moddleExtensions: {
        camunda: CamundaBpmnModdle
      },
      // 添加到扩展模块内
      additionalModules: [
        // 基础侧边栏渲染入口
        BpmnPropertiesPanelModule,
        // 侧边栏属性编辑表单构造器
        BpmnPropertiesProviderModule,
        CamundaPlatformPropertiesProviderModule,
        // 国际化
        // translate
      ]
    })
  // )
  createDiagram()
}
const download = () => {
  bpmnModeler!
    .saveXML({ format: true })
    .then((result: any) => {
      const { warnings, xml } = result
      if (warnings && warnings.length) {
        warnings.forEach((warn: any) => console.warn(warn))
      } else {
        // 下载文件
        setEncoded('diagram.bpmn', xml)
      }
    })
    .catch((err: any) => {
      const { warnings, message } = err
      console.log('failed to serialize BPMN 2.0 xml', warnings, message)
    })
}
const openFile = (file: any) => {
  const reader = new FileReader()
  // // 读取File对象中的文本信息，编码格式为UTF-8
  reader.readAsText(file, 'utf-8')
  reader.onload = async () => {
    // 读取完毕后将文本信息导入到Bpmn建模器
    await importXML(reader.result as string)
  }
}
const importXML = async (bpmn: string) => {
  bpmnModeler!
    .importXML(bpmn)
    .then((result: any) => {
      const { warnings } = result
      if (warnings && warnings.length) {
        warnings.forEach((warn: any) => console.warn(warn))
      } else {
        success()
      }
    })
    .catch((err: any) => {
      const { warnings, message } = err
      console.log('something went wrong:', warnings, message)
    })
}

const createDiagram = () => {
  bpmnModeler!
    .importXML(newDiagram)
    .then((result: any) => {
      const { warnings } = result
      if (warnings && warnings.length) {
        warnings.forEach((warn: any) => console.warn(warn))
      } else {
        success()
      }
    })
    .catch((err: any) => {
      const { warnings, message } = err
      console.log('could not import BPMN 2.0 XML', warnings, message)
    })
}
const setEncoded = (name: string, data: any) => {
  const encodedData = encodeURIComponent(data)
  const a = document.createElement('a')
  if (data) {
    const event = new MouseEvent('click')
    a.target = '_blank'
    a.download = name
    a.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData // 路径前拼上前缀，完整路径
    a.dispatchEvent(event)
  } else {
    a.remove()
  }
}
const upload = () => {
  bpmnModeler!
    .saveXML({ format: true })
    .then(async (result: any) => {
      const { warnings, xml } = result
      if (warnings && warnings.length) {
        warnings.forEach((warn: any) => console.warn(warn))
      }
    })
    .catch((err: any) => {
      const { warnings, message } = err
      console.log('failed to serialize BPMN 2.0 xml', warnings, message)
    })
}

onMounted(() => {
  initModeler()
})
const success = () => {
  bpmnModeler.get('canvas').zoom('fit-viewport')
  addModelerListener()
  addEventBusListener()
  addBpmnListener()
}
const addBpmnListener = () => {
  bpmnModeler.on('commandStack.changed', () => {
    console.log()
  })
}
const addModelerListener = () => {
  // 监听model
  // 'shape.removed', 'connect.end', 'connect.move'
  const events = ['shape.added', 'shape.move.end', 'shape.removed']
  events.forEach((event) => {
    bpmnModeler.on(event, (e: any) => {
      const elementRegistry = bpmnModeler.get('elementRegistry')
      const shape = e.element ? elementRegistry.get(e.element.id) : e.shape
      // console.log(shape)
      if (event === 'shape.added') {
        // console.log('新增了shape')
        // 展示新增图形的属性
        // key = e.element.id.replace('_label', '');
        // propsComponent = bpmnHelper.getComponentByEleType(shape.type);
        // element = e.element;
      } else if (event === 'shape.move.end') {
        // console.log('移动了shape')
        // 展示新增图形的属性
        // key = shape.id;
        // propsComponent = bpmnHelper.getComponentByEleType(shape.type);
        // element = e.shape;
      } else if (event === 'shape.removed') {
        // console.log('删除了shape')
        // 展示默认的属性
        // propsComponent = 'CommonProps'
      }
    })
  })
}
const addEventBusListener = () => {
  // 监听 element
  const eventBus = bpmnModeler.get('eventBus')
  const modeling = bpmnModeler.get('modeling')
  // // console.log(modeling)
  // const elementRegistry = bpmnModeler.get('elementRegistry')
  const eventTypes = ['element.click', 'element.changed', 'selection.changed']
  eventTypes.forEach(function (eventType) {
    eventBus.on(eventType, (e: any) => {
      const elementRegistry = bpmnModeler.get('elementRegistry')
      const shape = e.element ? elementRegistry.get(e.element.id) : e.shape
      if (eventType === 'element.click') {
        console.log('点击了element', e)
        if (shape.type === 'bpmn:StartEvent') {
          // console.log('点击了element', e)
          console.log(true)
        }
      } else if (eventType === 'element.changed') {
        // console.log('改变了element', e)
      } else {
        // console.log('selection.changed', e)
      }
    })
  })
}
</script>
<style scoped lang="scss">
.container {
  position: relative;
  height: 100%;
  text-align: left;
}
#modeler {
  height: 86vh;
  margin-bottom: 5px;
}
#canvas {
  height:100%;
  border: 1px solid rgb(121, 121, 121);
}
.bpp-properties-panel [type='text'] {
  box-sizing: border-box;
}
.panel {
  width: 400px;
  position: absolute;
  top: 1px;
  right: 1px;
  height: 100%;
  overflow: auto;
}
.action {
  display: flex;
  box-sizing: border-box;
  position: absolute;
  bottom: 5px;
  left: 5px;
  z-index: 100;
}
/* 右下角logo */
//:deep(.bjs-powered-by) {
//  display: none;
//}
</style>
